#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
品牌危机公关处理效果评估与预防机制构建 - 数据收集模块

此程序用于收集特定品牌的新闻报道、社交媒体讨论和官方声明，
并将数据存储为结构化格式，用于后续的危机处理效果评估。
"""

import os
import argparse
import logging
from datetime import datetime
from dotenv import load_dotenv

# 导入自定义模块
from brand_crisis_collector.news_crawler import NewsCrawler
from brand_crisis_collector.social_media_crawler import SocialMediaCrawler
from brand_crisis_collector.official_statement_crawler import OfficialStatementCrawler
from brand_crisis_collector.data_processor import DataProcessor
from brand_crisis_collector.evaluation_engine import EvaluationEngine
from brand_crisis_collector.prevention_generator import PreventionGenerator

# 加载环境变量
load_dotenv()

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(f"brand_crisis_collector_{datetime.now().strftime('%Y%m%d')}.log"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("brand_crisis_collector")

def setup_argparse():
    """设置命令行参数"""
    parser = argparse.ArgumentParser(description='品牌危机公关处理效果评估数据收集工具')
    
    parser.add_argument('--brand', type=str, required=True,
                        help='品牌名称，例如：小米、华为、苹果等')
    
    parser.add_argument('--keywords', type=str, nargs='+',
                        help='搜索关键词，可以是多个，例如：小米 Mix 4 发热')
    
    parser.add_argument('--crisis-keywords', type=str, nargs='+',
                        help='危机关键词，用于识别危机内容，例如：质量问题、爆炸、召回')
    
    parser.add_argument('--weibo-id', type=str,
                        help='官方微博账号ID，用于抓取官方声明')
    
    parser.add_argument('--official-website', type=str,
                        help='官方网站URL，用于抓取官方声明')
    
    parser.add_argument('--css-selector', type=str, default='.news-list .news-item',
                        help='官方网站新闻列表的CSS选择器')
    
    parser.add_argument('--use-selenium', action='store_true',
                        help='是否使用Selenium（用于需要JavaScript渲染的网站）')
    
    parser.add_argument('--news-pages', type=int, default=3,
                        help='新闻抓取页数，默认为3页')
    
    parser.add_argument('--social-pages', type=int, default=2,
                        help='社交媒体抓取页数，默认为2页')
    
    parser.add_argument('--official-pages', type=int, default=2,
                        help='官方声明抓取页数，默认为2页')
    
    parser.add_argument('--output-dir', type=str, default='output',
                        help='输出目录，默认为output')
    
    parser.add_argument('--db-only', action='store_true',
                        help='是否只处理已有的Excel文件并导入数据库，不进行新的爬取')
    
    parser.add_argument('--export-only', action='store_true',
                        help='是否只从数据库导出综合数据，不进行新的爬取和导入')
    
    parser.add_argument('--use-mock-data', action='store_true',
                        help='是否使用模拟数据，而不是实际抓取或从数据库加载')
    
    parser.add_argument('--crisis-event', type=str,
                        help='危机事件描述，例如：手机发热问题')
    
    parser.add_argument('--skip-data-collection', action='store_true',
                        help='跳过数据收集环节，直接进行评估和预防机制生成')
    
    return parser.parse_args()

def main():
    """主函数"""
    # 解析命令行参数
    args = setup_argparse()
    
    # 创建输出目录
    os.makedirs(args.output_dir, exist_ok=True)
    
    # 根据brand和keywords构建完整的搜索关键词
    brand = args.brand
    search_keywords = args.keywords or [brand]
    search_keywords = [f"{brand} {kw}" if brand not in kw else kw for kw in search_keywords]
    
    # 危机关键词
    crisis_keywords = args.crisis_keywords or ["问题", "危机", "投诉", "召回", "道歉", "退款", "不满"]
    
    # 文件名前缀
    file_prefix = f"{brand}_{datetime.now().strftime('%Y%m%d')}"
    
    # 输出文件路径
    news_file = os.path.join(args.output_dir, f"{file_prefix}_news_data.xlsx")
    social_file = os.path.join(args.output_dir, f"{file_prefix}_social_data.xlsx")
    official_file = os.path.join(args.output_dir, f"{file_prefix}_official_statements.xlsx")
    integrated_file = os.path.join(args.output_dir, f"{file_prefix}_integrated_crisis_data.xlsx")
    evaluation_report_file = os.path.join(args.output_dir, f"{file_prefix}_crisis_evaluation_report.xlsx")
    prevention_report_file = os.path.join(args.output_dir, f"{file_prefix}_crisis_prevention_report.xlsx")
    sentiment_trend_file = os.path.join(args.output_dir, f"{file_prefix}_sentiment_trend.png")
    crisis_radar_file = os.path.join(args.output_dir, f"{file_prefix}_crisis_radar.png")
    crisis_keywords_file = os.path.join(args.output_dir, f"{file_prefix}_crisis_keywords.png")
    
    if not args.skip_data_collection and not args.use_mock_data:
        # 初始化数据处理器
        processor = DataProcessor(db_connect=True)
        
        try:
            # 如果不是只导出数据，且不是只处理已有Excel文件
            if not args.export_only and not args.db_only:
                # 1. 爬取新闻数据
                logger.info(f"开始爬取品牌 '{brand}' 的相关新闻...")
                news_crawler = NewsCrawler()
                
                all_news = []
                for keyword in search_keywords:
                    baidu_news = news_crawler.search_baidu_news(keyword, pages=args.news_pages)
                    logger.info(f"从百度新闻获取了 {len(baidu_news)} 条关于 '{keyword}' 的新闻")
                    
                    weixin_articles = news_crawler.search_weixin_articles(keyword, pages=args.news_pages)
                    logger.info(f"从微信公众号获取了 {len(weixin_articles)} 条关于 '{keyword}' 的文章")
                    
                    all_news.extend(baidu_news + weixin_articles)
                
                if all_news:
                    news_crawler.save_to_excel(all_news, news_file)
                    logger.info(f"新闻数据已保存到 {news_file}")
                else:
                    logger.warning("未获取到任何新闻数据")
                
                # 2. 爬取社交媒体数据
                logger.info(f"开始爬取品牌 '{brand}' 的社交媒体讨论...")
                social_crawler = SocialMediaCrawler()
                
                all_social = []
                for keyword in search_keywords:
                    weibo_data = social_crawler.search_weibo(keyword, pages=args.social_pages)
                    logger.info(f"从微博获取了 {len(weibo_data)} 条关于 '{keyword}' 的内容")
                    
                    zhihu_data = social_crawler.search_zhihu(keyword, pages=args.social_pages)
                    logger.info(f"从知乎获取了 {len(zhihu_data)} 条关于 '{keyword}' 的内容")
                    
                    douyin_data = social_crawler.search_douyin_comments(keyword)
                    logger.info(f"从抖音获取了 {len(douyin_data)} 条关于 '{keyword}' 的模拟内容")
                    
                    all_social.extend(weibo_data + zhihu_data + douyin_data)
                
                if all_social:
                    social_crawler.save_to_excel(all_social, social_file)
                    logger.info(f"社交媒体数据已保存到 {social_file}")
                else:
                    logger.warning("未获取到任何社交媒体数据")
                
                # 3. 爬取官方声明
                logger.info(f"开始爬取品牌 '{brand}' 的官方声明...")
                official_crawler = OfficialStatementCrawler(use_selenium=args.use_selenium)
                
                all_statements = []
                
                # 从官方网站爬取
                if args.official_website:
                    website_statements = official_crawler.scrape_official_website(
                        website_url=args.official_website,
                        css_selector=args.css_selector,
                        keyword="声明",
                        max_pages=args.official_pages
                    )
                    logger.info(f"从官方网站获取了 {len(website_statements)} 条声明")
                    all_statements.extend(website_statements)
                
                # 从官方微博爬取
                if args.weibo_id:
                    weibo_statements = official_crawler.get_official_weibo_statements(
                        account_id=args.weibo_id,
                        keyword="声明",
                        pages=args.official_pages
                    )
                    logger.info(f"从官方微博获取了 {len(weibo_statements)} 条声明")
                    all_statements.extend(weibo_statements)
                
                if all_statements:
                    official_crawler.save_to_excel(all_statements, official_file)
                    logger.info(f"官方声明数据已保存到 {official_file}")
                else:
                    logger.warning("未获取到任何官方声明数据")
                
                # 关闭Selenium
                official_crawler.close()
            
            # 如果不是只导出数据
            if not args.export_only:
                # 4. 处理数据并导入数据库
                logger.info("开始处理数据并导入数据库...")
                
                # 处理新闻数据
                if os.path.exists(news_file):
                    news_count = processor.process_news_data(news_file)
                    logger.info(f"成功处理并导入 {news_count} 条新闻数据")
                
                # 处理社交媒体数据
                if os.path.exists(social_file):
                    social_count = processor.process_social_media_data(social_file)
                    logger.info(f"成功处理并导入 {social_count} 条社交媒体数据")
                
                # 处理官方声明数据
                if os.path.exists(official_file):
                    statement_count = processor.process_official_statement_data(official_file)
                    logger.info(f"成功处理并导入 {statement_count} 条官方声明数据")
            
            # 5. 生成集成数据
            logger.info(f"开始生成品牌 '{brand}' 的集成危机数据...")
            integrated_count = processor.generate_integrated_data(brand, crisis_keywords)
            logger.info(f"成功生成 {integrated_count} 条集成危机数据")
            
            # 6. 导出集成数据
            logger.info(f"开始导出品牌 '{brand}' 的集成危机数据...")
            if processor.export_integrated_data(brand, integrated_file):
                logger.info(f"集成危机数据已导出到 {integrated_file}")
            else:
                logger.warning("导出集成危机数据失败")
            
        except Exception as e:
            logger.error(f"数据收集和处理过程中出错: {str(e)}")
            raise
        
        finally:
            # 关闭数据库连接
            processor.close()
    
    # 如果使用模拟数据，跳过数据收集和处理
    if args.use_mock_data:
        logger.info("使用模拟数据进行分析")
        integrated_file = None  # 不使用真实文件，而是让评估引擎自动生成模拟数据
    
    # 运行评估引擎
    logger.info(f"开始评估品牌 '{brand}' 的危机处理效果...")
    engine = EvaluationEngine(brand, args.crisis_event, db_connect=(not args.use_mock_data))
    
    # 加载数据（从集成数据文件或使用模拟数据）
    from_excel = None
    if integrated_file and os.path.exists(integrated_file):
        from_excel = integrated_file
    
    data_count = engine.load_crisis_data(from_excel=from_excel)
    logger.info(f"评估引擎加载了 {data_count} 条数据")
    
    # 生成评估报告
    if engine.generate_evaluation_report(evaluation_report_file):
        logger.info(f"评估报告已生成: {evaluation_report_file}")
    else:
        logger.error("生成评估报告失败")
    
    # 绘制情感趋势图
    if engine.plot_sentiment_trend(sentiment_trend_file):
        logger.info(f"情感趋势图已生成: {sentiment_trend_file}")
    else:
        logger.error("绘制情感趋势图失败")
    
    # 运行预防机制生成器
    logger.info(f"开始生成品牌 '{brand}' 的危机预防机制...")
    generator = PreventionGenerator(brand)
    
    # 加载评估结果
    generator.load_evaluation_results(evaluation_report_file)
    
    # 加载危机数据
    crisis_data_file = None
    if integrated_file and os.path.exists(integrated_file):
        crisis_data_file = integrated_file
    
    generator.load_crisis_data(crisis_data_file)
    
    # 加载失败案例库
    generator.load_failure_cases()
    
    # 生成预防机制报告
    if generator.generate_prevention_report(prevention_report_file):
        logger.info(f"预防机制报告已生成: {prevention_report_file}")
    else:
        logger.error("生成预防机制报告失败")
    
    # 生成危机雷达图
    if generator.generate_crisis_radar_plot(crisis_radar_file):
        logger.info(f"危机雷达图已生成: {crisis_radar_file}")
    else:
        logger.error("生成危机雷达图失败")
    
    # 生成危机关键词云图
    if generator.generate_keyword_cloud(crisis_keywords_file):
        logger.info(f"危机关键词云图已生成: {crisis_keywords_file}")
    else:
        logger.error("生成危机关键词云图失败")
    
    logger.info("品牌危机评估与预防机制构建完成！")
    logger.info(f"所有输出文件已保存到 {args.output_dir} 目录")

if __name__ == "__main__":
    main()